<template>
	<div class="login-container">
		<!-- 视频区域 -->
		<video
			src="@/assets/video/zero.mp4"
			class="video"
			muted
			autoplay
			loop
		></video>

		<!-- 背景图区域 -->
		<div class="imgBox"></div>

		<el-form
			:model="loginForm"
			status-icon:false
			:rules="rules"
			ref="loginForm"
			label-width="100px"
			class="demo-loginForm"
		>
			<h1 class="title" v-text="title"></h1>
			<!-- 一开始是二维码角标, 点击之后变成电脑角标, 再次点击又切换 -->
			<i
				:class="['jiaobiao', 'iconfont', jiaobiao]"
				@click=";(isErweiLogin = !isErweiLogin), (isSmsLogin = false)"
			></i>
			<!-- <svg class="icon" aria-hidden="true">
        <use xlink:href="#icon-diannaojiaobiao"></use>
      </svg> -->

			<!-- 切换二维码登入控制条件 isErweiLogin -->
			<!-- 常规登入 -->
			<div class="common-login" v-if="!isErweiLogin && !isSmsLogin">
				<el-form-item label="用户名" prop="username">
					<el-input
						type="text"
						v-model="loginForm.username"
						autocomplete="off"
					></el-input>
				</el-form-item>

				<el-form-item label="密码" prop="password">
					<el-input
						type="password"
						v-model="loginForm.password"
						autocomplete="off"
					></el-input>
				</el-form-item>

				<el-form-item label="验证码" prop="captcha">
					<el-input
						v-model="loginForm.captcha"
						maxlength="5"
						class="captcha"
						@keydown.enter.native="submitForm('loginForm')"
					></el-input>
					<span class="captcha-svg" v-loading="loading">
						<i v-html="captchaSvg" @click="updateCaptcha"></i>
					</span>
				</el-form-item>
				<el-form-item>
					<el-button type="primary" @click="submitForm('loginForm')">
						登入
					</el-button>
				</el-form-item>
				<!-- 手机登入图标按钮  -->
				<el-form-item>
					<div class="sms">
						<svg class="icon phone" aria-hidden="true">
							<use xlink:href="#icon-iphone"></use>
						</svg>
						<a
							href="javascript:;"
							style="color: #fff; font-size: 16px"
							@click="isSmsLogin = true"
						>
							切换短信登入
						</a>
					</div>
				</el-form-item>
			</div>

			<!-- 二维码登入  -->
			<div class="erweima" v-else-if="isErweiLogin && !isSmsLogin">
				<div class="img" v-loading="qrLoading">
					<img :src="imgBase64Url" alt="" width="200px" />
					<i
						class="mask"
						:style="qrStyle"
						v-show="showQrMask"
						@click="getQrcode"
					></i>
				</div>
				<p>
					<svg class="icon weixin" aria-hidden="true">
						<use xlink:href="#icon-weixin"></use>
					</svg>
					<b v-text="qrTip"></b>
				</p>
			</div>

			<!-- 短信验证码登入 -->
			<div class="smsContainer" v-else>
				<el-form-item label="手机号">
					<el-input
						class="phoneNumberIpt"
						maxlength="11"
						v-model="phoneNumber"
					></el-input>
					<span
						class="captcha-svg"
						style="color: #888;, line-height: 45px;text-decoration: underline;"
						v-text="smsRetryMsg"
						@click="sendSmsCode"
					></span>
				</el-form-item>
				<el-form-item label="验证码">
					<el-input
						v-model="smsCode"
						@keydown.enter.native="smsSubmit"
					></el-input>
				</el-form-item>
				<el-form-item>
					<el-button type="primary" @click="smsSubmit">登入</el-button>
				</el-form-item>
			</div>
		</el-form>
	</div>
</template>

<script>
// 引入api中的方法
import * as api from '@/api/users'
// 引入socket.io  连接服务器
import socketIo from 'socket.io-client'
// 引入生成二维码的插件qrcode
import qr from 'qrcode'
// 引入扫码成功和失败的图片 得到的是图片的地址
import scancodeSuccessPic from '@/assets/imgs/scancode.png'
import invalidPic from '@/assets/imgs/invalidQr.png'

// 映射 vuex 的辅助函数
import { mapMutations } from 'vuex'

// 验证码校验函数
var validateCaptcha = (rule, value, callback) => {
	if (!value) {
		callback(new Error('请输入验证码'))
	} else {
		callback()
	}
}
// 用户名校验函数
var validateUsername = (rule, value, callback) => {
	let pattarn = /^[a-zA-Z0-9_-]{4,16}$/
	if (pattarn.test(value)) {
		callback()
	} else {
		callback(new Error('请输入4-16位用户名'))
	}
}
// 密码校验函数
var validatePassword = (rule, value, callback) => {
	if (value === '') {
		callback(new Error('请输入密码'))
	} else {
		callback()
	}
}

export default {
	name: 'Login',
	data() {
		return {
			smsCode: '', // 手机验证码
			smsDisabled: false, // 控制是否能够再次发送验证码
			smsRetryMsg: '点击发送验证码', // xx秒之后可重新发送验证码
			captchaSvg: '', // 验证码svg
			loading: true, // 获取二维码加载动画布尔值
			isErweiLogin: false, // 是否是二维码登入
			phoneNumber: '', // 验证手机号码
			isSmsLogin: false, // 手机短信登入
			qrTip: '请使用手机微信扫码登入', // 切换到二维码登入时的提示文字
			imgBase64Url: '', // 二维码地址
			showQrMask: false, // 是否显示二维码遮罩
			qrLoading: true, // 二维码加载动画布尔值

			loginForm: {
				username: '',
				password: '',
				captcha: ''
			},
			rules: {
				username: [{ validator: validateUsername, trigger: 'blur' }],
				password: [{ validator: validatePassword, trigger: 'blur' }],
				captcha: [{ validator: validateCaptcha, trigger: 'blur' }]
			},
			isScanCodeSuccess: false, // 是否二维码登入成功
			// mask 遮罩的样式
			qrStyle: {
				backgroundImage: `url(${invalidPic})`
			}
		}
	},
	computed: {
		// 计算图标的类名
		jiaobiao() {
			return this.isErweiLogin ? 'icon-diannaojiaobiao' : 'icon-erweimajiaobiao'
		},
		// 计算title 内容
		title() {
			return this.isErweiLogin ? '微信扫码登入' : '寻找OnePiece'
		}
	},
	created() {
		// 调用获取验证码的方法
		this.updateCaptcha()
	},
	methods: {
		// 映射 vuex mutataions 中的方法
		...mapMutations(['SET_USERINFO']),
		// 封装短信登入相关的方法
		async sendSmsCode() {
			// 判断一下是否可以发送短信, 通过smsDisabled来控制
			if (this.smsDisabled) {
				this.$message.error('1分钟内只能发送一次')
				// 如果值为true 不执行 直接return
				return
			}
			// 获取手机号, 传递给后台, 调用发送短信的接口
			// console.log(this.phoneNumber)
			let smsResult = await api.getSmsCode(this.phoneNumber)
			// 先解构内容
			let { state } = smsResult.data
			if (state) {
				// 锁住smsDisabled, 不能再发送了
				this.smsDisabled = true
				// 提示用户短信发送成功
				this.$message.success('短信发送成功')
				// 计数变量添加到实例上
				this.smsSecond = 60
				// 短信发送需要进入倒计时 定时器添加到 vue 实例上
				this.smsInterval = setInterval(() => {
					this.smsSecond--
					if (this.smsSecond == 0) {
						// 清除定时器
						clearInterval(this.smsInterval)
						// 提示文字要复原
						this.smsRetryMsg = `点击发送验证码`
						// 解锁smsDisabled 可以继续发送短信了
						this.smsDisabled = false
						return
					}
					this.smsRetryMsg = `${this.smsSecond}秒后重新发送`
				}, 1000)
			}
		},

		// 手机登入
		async smsSubmit() {
			// 获取登入数据
			let smsLoginRes = await api.smsLogin(this.smsCode)
			// console.log(smsLoginRes)
			// 判断登入状态, 如果登入成功, 将数据存储到本地
			let {
				state,
				userInfo,
				permission: { buttons },
				token
			} = smsLoginRes.data

			// 把 token userInfo permisssion 存本地
			if (state) {
				localStorage.setItem('yue-promissionBtn', JSON.stringify(buttons))
				localStorage.setItem('yue-token', token)
				// 调用vuex的方法, 设置用户信息
				this.SET_USERINFO(userInfo)
				// 跳转到欢迎页面
				this.$router.push('/')
			}

			// 打开加载动画
			// 按钮权限
			// 按钮权限
		},

		// 封装一个获取二维码地址的方法
		async getQrcode(sid) {
			// 将提示文字变更
			this.qrTip = '请使用手机微信扫码登入'
			// 先清掉上一次二维码图片
			this.imgBase64Url = ''
			// 先关掉qrcode的遮罩
			this.showQrMask = false
			// 把加载二维码动画打开
			this.qrLoading = true
			// console.log(sid)
			// 如果有就用本地的 没有就用传过来的sid
			sid = localStorage.getItem('yue-sid') ?? sid

			// 从本地取出sid
			// 调用接口获取二维码 url
			let qrResult = await api.getQrcode(sid)
			// console.log(qrResult)
			// 解构 scanCodeUrl 和 后端的状态码
			let { scanCodeUrl, state: getQrState } = qrResult.data
			// 判断服务器状态
			if (getQrState) {
				// 如果请求成功
				// 使用qrcode插件, 将scanCodeUrl 变成一个二维码
				qr.toDataURL(scanCodeUrl, (err, imgBase64Url) => {
					if (err) {
						// 出错的情况 抛出错误
						return this.$messageBox.error(err)
					}
					// console.log(imgBase64Url)
					// 成功的情况把二维码图片地址赋值给定义在data中的 imgBase64Url
					this.imgBase64Url = imgBase64Url
					// 获取到二维码地址 关掉二维码的加载动画
					this.qrLoading = false
				})
			}
		},

		// 封装一个方法, 专门用于获取验证码
		updateCaptcha() {
			// 打开加载动画
			this.loading = true
			api.getCaptcha().then(res => {
				// console.log(res)
				let { img } = res.data // 解构验证码
				this.captchaSvg = img
				// 请求到数据关闭加载动画
				this.loading = false
			})
		},
		// 常规登入
		async submitForm(formName) {
			// 登入逻辑

			// 1. 先要进行本地的表单校验

			// 2. 表单校验之后, 通过v-model获取输入的 username password

			// 3. 校验验证码

			// 4. 校验通过之后 发起请求  请求登入接口 掺入用户名和密码

			// 5. 跳转到主页, 显示主页

			// formName 是表单的ref名字
			// 这里必须使用 箭头函数 让this指向当前组件
			this.$refs[formName].validate(valid => {
				// console.log(valid)
				if (valid) {
					// 打开加载动画
					const loading = this.$loading({
						lock: true,
						text: '正在登入',
						spinner: 'el-icon-loading',
						background: 'rgba(0, 0, 0, 0.7)'
					})
					// 本地表达验证通过
					let { username, password, captcha } = this.loginForm
					// 校验验证码
					api.verifyCaptcha(captcha).then(async res => {
						// console.log(res)
						let { state } = res.data // 解构返回的结果
						if (state) {
							// 验证码正确
							let loginRes = await api.login(username, password)
							// console.log(loginRes)
							let { state: loginState, msg, token, userInfo } = loginRes.data
							let buttons = loginRes.data.permission?.buttons ?? []
							if (loginState) {
								// console.log('token', token)
								// 登入成功
								// 关闭登入加载动画
								loading.close()
								// 将token存到 localStorage
								localStorage.setItem('yue-token', token)
								// 存按钮权限
								localStorage.setItem('yue-buttons', JSON.stringify(buttons))
								// console.log(userInfo)
								// 调用vuex的方法, 设置用户信息
								this.SET_USERINFO(userInfo)

								// 跳转页面
								this.$router.push('/')
								// 提示登入成功
								this.$message({
									message: msg + ',正在跳转..',
									type: 'success',
									duration: 1000 // 提示收起时间
								})
							} else {
								// 登入失败 关闭载入动画
								loading.close()
							}
						} else {
							// 登入失败 关闭载入动画
							loading.close()
							// 刷新验证码 调用刷新验证码
							this.updateCaptcha()
							// 输入的验证码清空
							this.loginForm.captcha = ''
						}
					})
				} else {
					// 表单验证不通过
					// 关闭加载动画
					loading.close()
					return false
				}
			})
		}
	},
	watch: {
		// 监听短信切换逻辑
		isSmsLogin(val) {
			// 不是短信登录的时候, 清掉定时器
			if (!val) {
				// 判断是否发送成功 成功就清除掉
				if (this.smsInterval) {
					clearInterval(this.smsInterval)
				}
				// 将短信登入的文字提示复原
				this.smsRetryMsg = '点击发送验证码'
			}
		},

		// 监听切换二维码登入的字段
		isErweiLogin(isErwei) {
			if (isErwei) {
				// 切换成了二维码登入
				// 打开二维码加载动画
				this.qrLoading = true
				// 切换到二维码登入 需要把遮罩关掉
				this.showQrMask = false
				// 建立 socket 连接
				// https协议, 要使用wss协议
				let io = socketIo('wss://chst.vip')

				// 连接成功
				io.on('connectSuccess', async data => {
					// console.log(data)
					// 从data中解构 sid
					let { sid } = data
					// 把客户端唯一标识存到本地
					localStorage.setItem('yue-sid', sid)
					this.getQrcode(sid)
				})

				// 扫码成功 监听事件 用户微信扫码成功返回临时code
				io.on('scancodeSuccess', async data => {
					// 显示二维码的遮罩 并且把背景图 片换成扫码成功的背景图片
					this.showQrMask = true
					this.qrStyle.backgroundImage = `url(${scancodeSuccessPic})`
					// console.log(data)
					let { state: scanCodeState, wechatCode } = data
					if (scanCodeState) {
						// 扫码成功了
						let scanCodeRes = await api.wechatLogin(wechatCode)
						// 得到用户信息
						// console.log(scanCodeRes)
						// 解构内容
						let {
							state,
							userInfo,
							permission: { buttons },
							token
						} = scanCodeRes.data
						// 把 token userInfo permisssion 存本地
						if (state) {
							// localStorage.setItem('yue-userInfo', JSON.stringify(userInfo))
							// 存按钮权限
							localStorage.setItem('yue-buttons', JSON.stringify(buttons))
							localStorage.setItem('yue-token', token)
							// 调用vuex的方法, 设置用户信息
							this.SET_USERINFO(userInfo)
							// 跳转到欢迎页面
							this.$router.push('/')
							// 关闭二维码遮罩
							this.showQrMask = false
						}
					}
				})
				// 二维码失效 无效二维码主体内容
				io.on('invalidCode', data => {
					this.qrStyle.backgroundImage = `url(${invalidPic})`
					// console.log(data)
					let { state } = data
					if (!state) {
						// 如果二维码失效了把二维码遮罩打开
						this.showQrMask = true
						// 将提示文字变更
						this.qrTip = '二维码失效, 请点击重新获取二维码'
					}
				})
			}
		}
	}
}
</script>

<style lang="less" scoped>
// 1. 找类名
// 2. 看权重
// 3. 是否需要深度

.login-container {
	text-align: center;
	color: #fff;
	height: 100%;

	.video {
		width: 100%;
		// height: 100%;
		position: fixed;
		left: 0;
		top: 0;
		right: 0;
		bottom: 0;
	}

	.imgBox {
		// background-image: url('@/assets/imgs/bg2.png');
		background-repeat: no-repeat;
		position: fixed;
		width: 20%;
		height: 40%;
		background-size: 100% 100%;
		left: 20%;
		top: 40%;
		opacity: 0.5;
	}

	h1 {
		margin-bottom: 50px;
	}

	.jiaobiao {
		font-size: 60px;
		color: #fff;
		position: absolute;
		right: -2px;
		top: -2px;
		cursor: pointer;
		opacity: 0.7;
	}
	.el-form {
		position: fixed;
		right: 10%;
		top: 25%;
		border-radius: 5px;
		width: 400px;
		background-color: rgba(0, 0, 0, 0.3);
		padding: 80px 0 50px 0;
		box-sizing: border-box;

		// 常规登入
		.el-input {
			width: 250px;

			&.captcha {
				width: 100px;
				vertical-align: top;
				/deep/.el-input__inner {
					width: 100%;
					height: 45px;
					border-radius: 5px 0 0 5px;
					border: 0;
					font-size: 18px;
				}
			}
			/deep/ .el-input__inner {
				width: 250px;
				padding-left: 10px;
				font-size: 16px;
			}
		}

		.captcha-svg {
			background: #fff;
			display: inline-block;
			height: 45px;
			width: 150px;
			text-align: center;
			cursor: pointer;
			border: 0;
			border-radius: 0 5px 5px 0;
		}

		/deep/ .el-form-item__label {
			color: #fff;
			width: 80px !important;
			padding: 0;
		}
		/deep/.el-form-item__content {
			width: 280px;
			margin-left: 80px !important;

			.el-form-item__error {
				left: 16px;
			}
			.el-button--primary {
				width: 250px;
				background: linear-gradient(90deg, #1596fb, #002dff);
			}

			.phone {
				vertical-align: middle;
				font-size: 2.2em;
			}
		}

		// 二维码登入
		.erweima {
			.img {
				display: inline-block;
				position: relative;
				width: 200px;
				height: 200px;

				.mask {
					width: 100%;
					height: 100%;
					opacity: 0.8;
					background-color: #fff;
					position: absolute;
					left: 0;
					background-size: 50%;
					background-repeat: no-repeat;
					background-position: 50%;
					cursor: pointer;
				}

				img {
					position: absolute;
					left: 0;
				}
			}

			b {
				font-weight: normal;
			}

			.weixin {
				margin-right: 5px;
				vertical-align: middle;
				font-size: 30px;
			}
		}

		// 短信验证登入
		.phoneNumberIpt {
			width: 135px;
			height: 45px;
			vertical-align: top;
			/deep/.el-input__inner {
				width: 100%;
				height: 45px;
				border: 0;
				border-radius: 4px 0 0 4px;
				font-size: 16px;
			}
		}

		.smsContainer {
			.captcha-svg {
				width: 115px !important;
			}
		}
	}
}
</style>
